
/*
    int、double、str generic.
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>
#include <stdbool.h>
#include <tchar.h>
#include <iso646.h>
#define _BO_C
#define _BOAPI
#include ".\BasicObject.h"

_BOAPI _Bool bo_equal(bo_datum *self, bo_datum *obj)
{
    if(self->type != obj->type) {
        return false;
    }
    switch (self->type)
    {
    case BT_NONE: {
        return true;
    }
        break;
    
    case BT_INT: {
        return self->i == obj->i;
    } break;
    
    case BT_FLOAT: {
        return self->f == obj->f;
    } break;
    
    case BT_STR: {
        return _tcscmp(self->s, obj->s) == 0;
    } break;
    
    default:
        return true; // all invalid
    }
}

BO_DATA *__Bo_ObtainPtr(BOBJECT *self)
{
    int nl = self->num;
    BO_DATA *_this = &(self->data);
    while(nl > 0) {
        nl--;
        _this = _this->next;
    }
    return _this;
}
errno_t __Bo_Allocate(BOBJECT *self)
{
    if(self->ind >= BO_DATALEN) {
        BO_DATA *_this = __Bo_ObtainPtr(self);
        _this->next = (struct BO_DATA *)malloc(sizeof(BO_DATA) * BO_DATALEN);
        _this = _this->next;
        _this->next = NULL;
        self->ind = 0;
        self->num ++;
        return (errno_t)(_this != __Bo_ObtainPtr(self));
    }
    else {
        return 1;
    }
}

_BOAPI BOBJECT CreateObject()
{
    BOBJECT self;
    self.num = 0;
    self.ind = 0;
    self.data.next = NULL;
    return self;
}
_BOAPI void BO_PushInt(BOBJECT *self, BOINT i)
{
    int nl = self->num;
    BO_DATA *_this = &(self->data);
    while(nl > 0) {
        nl--;
        _this = _this->next;
    }
    _this->dat[self->ind].type = BT_INT;
    _this->dat[self->ind].i = i;
    self->ind ++;
    if(self->ind >= BO_DATALEN) {
        __Bo_Allocate(self);
    }
}
_BOAPI void BO_PushFloat(BOBJECT *self, BOFLOAT f)
{
    BO_DATA *_this = __Bo_ObtainPtr(self);
    _this->dat[self->ind].type = BT_FLOAT;
    _this->dat[self->ind].f = f;
    self->ind ++;
    if(self->ind >= BO_DATALEN) {
        __Bo_Allocate(self);
    }
}
_BOAPI void BO_PushString(BOBJECT *self, TCHAR *s)
{
    BO_DATA *_this = __Bo_ObtainPtr(self);
    _this->dat[self->ind].type = BT_STR;
    const int sl = _tcslen(s);
    //wprintf(L"\t\t*** getlen:%d", sl);
    _this->dat[self->ind].s = (TCHAR*)malloc(sizeof(TCHAR) * (sl + 1));
    //wprintf(L"\t\t*** malloc");
    /*if(_this->dat[self->ind].s == NULL ){
        printf("???nullpointerexception???@%p\n", _this->dat[self->ind].s);
        return ;
    }*/
    //_tcscpy_s(_this->dat[self->ind].s, sl, s);
    //这b东西为什么用不了?
    {
        TCHAR *sp = _this->dat[self->ind].s;
        int i = 0;
        while(i < sl && s[i] != 0) {
            *sp = s[i];
            i++;
            sp++;
        }
        *sp = 0;
    }
    //wprintf(L"\t\t*** cpy");
    self->ind ++;
    if(self->ind >= BO_DATALEN) {
        __Bo_Allocate(self);
    }
}
_BOAPI bo_datum BO_FindDatum(BOBJECT *self, int index)
{
    bo_datum* obj = BO_GetDatum(self, index);
    if(obj == NULL) {
        return BO_NULL;
    }else {
        return *obj;
    }
}
_BOAPI bo_datum* BO_GetDatum(BOBJECT *self, int index)
{
    BO_DATA *_this = &self->data;
    while(index >= BO_DATALEN) {
        index -= BO_DATALEN;
        _this = _this->next;
        if(_this == NULL) {
            return NULL;
        }
    }
    if(_this->next == NULL && index >= self->ind) {
        return NULL;
    }
    else {
        return &(_this->dat[index]);
    }
}
_BOAPI int BO_SeekDatum(BOBJECT *self, bo_datum *dat)
{
    BO_DATA *_this = &self->data;
    int i = 0;
    int nl = 0;
    int index = 0;
    while (true)
    {
        if (nl >= self->num) {
            break;
        }
        while(nl < self->num) {
            for (int j = 0; j < BO_DATALEN; j++) {
                if(bo_equal(&_this->dat[j], dat)) {
                    return index;
                }
                index++;
            }
            _this = _this->next;
            nl++;
            break;
        }
    }
    for (int j = 0; j < self->ind; j++) {
        if(bo_equal(&_this->dat[j], dat)) {
            return index;
        }
        index++;
    }
    return -1;
}
_BOAPI errno_t BO_FreeObject(BOBJECT *self){
    BO_DATA *_this = &self->data;
    BO_DATA *_next = &self->data;
    int nl = 0;
    while (nl < self->num)
    {
        for(int j = 0; j < BO_DATALEN; j++) {
            if (_this->dat[j].type == BT_STR) {
                free(_this->dat[j].s);
                _this->dat[j].s = NULL;
            }
        }
        nl++;
        _this = _this->next;
    }
    for(int j = 0; j < self->ind; j++) {
        if (_this->dat[j].type == BT_STR) {
            free(_this->dat[j].s);
            _this->dat[j].s = NULL;
        }
    }
    _this = &self->data;
    _next = _this->next;
    if(_next == NULL) {
        return 0;
    } else {
        _this = _next;
        _next = _this->next;
        free(_this);
        _this = NULL;
    }
    while(_next != NULL) {
        _this = _next;
        _next = _this->next;
        free(_this);
        _this = NULL;
    }
    return 0;
}